﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NugetPublishWizard.Models;
using System.IO;
using System.Globalization;
using System.Diagnostics;
using NugetPublishWizard.UI;
using NugetPublishWizard.NugetFeedService;
using System.Threading;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace NugetPublishWizard
{
    public partial class MainForm : Form
    {
        enum ActionType
        {
            Create, CreateFromProject, CreateFromFolder, Push, Publish, Remove, PackageStat
        }

        NugetPackage _package = new NugetPackage();
        TreeNode contentNode = new TreeNode("Content");
        TreeNode libNode = new TreeNode("Lib");
        private ActionType _Mode = ActionType.Create;
        private List<string> _ignoredDirectories = new List<string>(new string[] { ".svn", "bin", "obj", "properties" });
        private List<string> _ignoredFiles = new List<string>(new string[] { ".sln", ".csproj", ".user", ".vbproj", ".suo" });
        private string _selectDefault = "<select>";
        private int _lastBuildPanelEntryTop = 0;

        public MainForm()
        {
            Initialize();
        }

        public MainForm(string projectPath, string activeConfigurationName)
        {
            Initialize();
        }

        private void Initialize()
        {
            InitializeComponent();

            this.MaximumSize = this.Size;

            this.nugetPackageMetaDataBindingSource.DataSource = _package.MetaData;

            this._page6ApiKeyTextBox.Text = NugetPublishWizard.Properties.Settings.Default.ApiKey;

            foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
                this._page4LanguageComboBox.Items.Add(culture.EnglishName);
            this._page4LanguageComboBox.SelectedItem = "English";

            contentNode.Checked = true;
            libNode.Checked = true;

            _page5PackageContentTreeView.Nodes.Add(contentNode);
            _page5PackageContentTreeView.Nodes.Add(libNode);
            _pageStartExistingPackagePath.Text = _selectDefault;
            _pageStartCreateBasedOnFolderLabel.Text = _selectDefault;
            _pageStartCreateBasedOnProjectPathLabel.Text = _selectDefault;
            //_page6SaveTemplatePath.Text = _selectDefault;

            this._page5PackageContentTreeView.ExpandAll();
            HidePag1Panels();
        }

        private void modeCreateFromScratchRadio_CheckedChanged(object sender, EventArgs e)
        {
            HidePag1Panels();

            if (sender == _pageStartModeCreateFromScratchRadio) { }
            else if (sender == _pageStartModeCreateBasedOnFolderRadio)
                _page1CreateBasedOnFolderOptions.Visible = true;
            else if (sender == _pageStartModeCreateBasedOnProjectRadio)
                _page1BasedOnProjectOptions.Visible = true;
            else
            {
                _pageStartApiKey.Visible = true;
                _pageStartNugetServer.Visible = true;
                if (sender == _pageStartModePushRadio)
                    _page1ChooseExistingPackagePanel.Visible = true;
                if (sender == _pageStartModePublishRadio || sender == _pageStartModeRemoveFromLiveFeedRadio)
                    _page1PublishRemoveOptions.Visible = true;
                else if (_pageStartModePackageStat.Checked)
                {
                    _pageStartApiKey.Visible = false;
                    _page1PublishRemoveOptions.Visible = true;
                }
            }
        }

        private void HidePag1Panels()
        {
            _page1BasedOnProjectOptions.Visible = false;
            _page1CreateBasedOnFolderOptions.Visible = false;
            _page1PublishRemoveOptions.Visible = false;
            _page1ChooseExistingPackagePanel.Visible = false;
            _pageStartNugetServer.Visible = false;
            _pageStartApiKey.Visible = false;
        }

        private void _page3_Validating(object sender, CancelEventArgs e)
        {
            if (errorProvider1.GetError(this._page4ProjectUrlTextBox) != string.Empty ||
                errorProvider1.GetError(this._page4IconUrlTextBox) != string.Empty ||
                errorProvider1.GetError(this._page4LicenseUrlTextBox) != string.Empty ||
                errorProvider1.GetError(this._page4RequireLicenseAcceptanceCheckBox) != string.Empty)
                this._wizard.SelectedPage = this._page3;
        }

        #region Add / Remove Author
        private void addAuthorButton_Click(object sender, EventArgs e)
        {
            if (this._page2AddAuthorTextBox.Text.Trim() == string.Empty)
                return;

            this._page1AuthorslistBox.Items.Add(this._page2AddAuthorTextBox.Text.Trim());
            this._page2AddAuthorTextBox.Text = string.Empty;
        }

        private void authorslistBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            this._page2RemoveAuthorButton.Enabled = true;
        }

        private void removeAuthorButton_Click(object sender, EventArgs e)
        {
            this._page1AuthorslistBox.Items.Remove(this._page1AuthorslistBox.SelectedItem);
        }
        #endregion

        #region Add /Remove Owner
        private void addOwnerButton_Click(object sender, EventArgs e)
        {
            if (this._page4AddOwnerTextBox.Text.Trim() == string.Empty)
                return;

            this._page4AddOwnersListBox.Items.Add(this._page4AddOwnerTextBox.Text.Trim());
            this._page4AddOwnerTextBox.Text = string.Empty;
        }

        private void OwnerslistBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            this._page4RemoveOwnerButton.Enabled = true;
        }

        private void removeOwnerButton_Click(object sender, EventArgs e)
        {
            this._page4AddOwnersListBox.Items.Remove(this._page4AddOwnersListBox.SelectedItem);
        }
        #endregion

        #region Add / Remove Tags
        private void addTagButton_Click(object sender, EventArgs e)
        {
            if (this._page4AddTagTextBox.Text.Trim() == string.Empty)
                return;

            this._page4TagsListBox.Items.Add(this._page4AddTagTextBox.Text.Trim().Replace(" ",""));
            this._page4AddTagTextBox.Text = string.Empty;
        }

        private void TagslistBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            this._page4RemoveTagButton.Enabled = true;
        }

        private void removeTagButton_Click(object sender, EventArgs e)
        {
            this._page4TagsListBox.Items.Remove(this._page4TagsListBox.SelectedItem);
        }
        #endregion

        #region Find / Add / Remove Dependencies
        private void findDependencieButton_Click(object sender, EventArgs e)
        {
            this._page3FindDependencieButton.Enabled = false;
            this._page3FindDependencieTextBox.Enabled = false;
            this._page3FindDependencieSpinning.Tag = null;
            List<NugetDependencie> items = new List<NugetDependencie>();

            new Thread(new ThreadStart(delegate
            {
                this.Invoke(new SetFindidingDepedencyProcess(setFindidingDepedencyProcess), new object[] {
                        ProcessResult.None, ProcessState.Running, null, null
                    });

                NugetFeedService.GalleryFeedContext c = new NugetPublishWizard.NugetFeedService.GalleryFeedContext(new Uri(this._pageStartNugetServerTextBox.Text + "FeedService.svc"));
                try
                {
                    foreach (var package in (from p in c.Packages where p.Id.Contains(_page3FindDependencieTextBox.Text) select p).ToList())
                    {
                        items.Add(new NugetDependencie()
                        {
                            Id = package.Id,
                            Version = package.Version
                        });
                    }

                    this.Invoke(new SetFindidingDepedencyProcess(setFindidingDepedencyProcess), new object[] {
                        ProcessResult.Success, ProcessState.Finished, items, null
                    });
                }
                catch (Exception ex)
                {
                    this.Invoke(new SetFindidingDepedencyProcess(setFindidingDepedencyProcess), new object[] {
                        ProcessResult.Failed, ProcessState.NotStarted, null, ex
                    });
                }
            })).Start();
        }

        private delegate void SetFindidingDepedencyProcess(ProcessResult result, ProcessState state, List<NugetDependencie> list, Exception ex);
        private void setFindidingDepedencyProcess(ProcessResult result, ProcessState state, List<NugetDependencie> list, Exception ex)
        {
            this._page3FindDependencieSpinning.State = state;
            this._page3FindDependencieSpinning.Result = result;
            this._page3FindDependencieSpinning.Visible = true;

            if (result == ProcessResult.Success)
            {
                this._page3FindDependencieSpinning.Visible = false;

                this._page3AvailableDependencies.Items.Clear();
                foreach (NugetDependencie n in list) 
                {
                    this._page3AvailableDependencies.Items.Add(n);
                }

                this._page3FindDependencieButton.Enabled = true;
                this._page3FindDependencieTextBox.Enabled = true;
            }
            else if (result == ProcessResult.Failed)
            {
                this._page3FindDependencieSpinning.Tag = ex;
                this._page3FindDependencieButton.Enabled = true;
                this._page3FindDependencieTextBox.Enabled = true;
            }
        }

        private void addDependencieButton_Click(object sender, EventArgs e)
        {
            if (_page3AvailableDependencies.SelectedItem == null)
                return;

            NugetDependencie dependencie = new NugetDependencie()
            {
                Id = ((NugetDependencie)_page3AvailableDependencies.SelectedItem).Id,
                Version = "newest",
            };

            if (dependenciesListBox.Items.Contains(dependencie))
            {
                MessageBox.Show("The package is already in your dependencie list", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            this.dependenciesListBox.Items.Add(dependencie);
        }

        private void availableDependencies_SelectedIndexChanged(object sender, EventArgs e)
        {
            _page3AddDependencieButton.Enabled = true;
            _page3AddDependencieVersionButton.Enabled = true;
        }

        private void addDependencieVersionButton_Click(object sender, EventArgs e)
        {
            if (_page3AvailableDependencies.SelectedItem == null)
                return;

            NugetDependencie dependencie = new NugetDependencie()
            {
                Id = ((NugetDependencie)_page3AvailableDependencies.SelectedItem).Id,
                Version = ((NugetDependencie)_page3AvailableDependencies.SelectedItem).Version,
            };

            if (dependenciesListBox.Items.Contains(dependencie))
            {
                MessageBox.Show("The package is already in your dependencie list", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            this.dependenciesListBox.Items.Add(dependencie);
        }

        private void removeDependencieButton_Click(object sender, EventArgs e)
        {
            if (this.dependenciesListBox.SelectedItem == null)
                return;
            this.dependenciesListBox.Items.Remove(this.dependenciesListBox.SelectedItem);
        }


        private void findDependencieSpinning_Click(object sender, EventArgs e)
        {
            if (_page3FindDependencieSpinning.Tag != null)
            {
                Exception ex = (Exception)_page3FindDependencieSpinning.Tag;
                MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void addLocalDependencie_Click(object sender, EventArgs e)
        {
            if (_page3LocalDependencieIdTextBox.Text == string.Empty
                || !NugetPackageMetaData.IsValidId(_page3LocalDependencieIdTextBox.Text))
            {
                errorProvider1.SetError(_page3LocalDependencieIdTextBox, "Please provide the package id");
                return;
            }
            else errorProvider1.SetError(_page3LocalDependencieIdTextBox, string.Empty);

            System.Version v;
            if (!System.Version.TryParse(_page3LocalDependencieVersionTextBox.Text, out v))
            {
                errorProvider1.SetError(_page3LocalDependencieVersionTextBox, "Please provide a valid version (1.0.0.0, 1.0, ...)");
                return;
            }
            else errorProvider1.SetError(_page3LocalDependencieVersionTextBox, string.Empty);

            NugetDependencie dependencie = new NugetDependencie()
            {
                Id = _page3LocalDependencieIdTextBox.Text,
                Version = _page3LocalDependencieVersionTextBox.Text
            };

            if (dependenciesListBox.Items.Contains(dependencie))
            {
                MessageBox.Show("This package is already in your dependencie list", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            this.dependenciesListBox.Items.Add(dependencie);
        }
        #endregion

        #region Before / After -SwitchPages
        private void _wizard_BeforeSwitchPages(object sender, CristiPotlog.Controls.Wizard.BeforeSwitchPagesEventArgs e)
        {
            errorProvider1.SetError(_pageStartCreateBasedOnProjectPathLabel, string.Empty);
            errorProvider1.SetError(_pageStartCreateBasedOnFolderLabel, string.Empty);
            errorProvider1.SetError(_pageStartApiKeyTextBox2, string.Empty);
            errorProvider1.SetError(_pageStartExistingPackagePath, string.Empty);
            errorProvider1.SetError(_pageStartPublishRemoveId, string.Empty);
            errorProvider1.SetError(_pageStartPublishRemoveVersion, string.Empty);
            errorProvider1.SetError(this._page1AuthorslistBox, string.Empty);
            errorProvider1.SetError(_page6OutputDirectoryLabel, string.Empty);
            errorProvider1.SetError(_page6ApiKeyTextBox, string.Empty);
            errorProvider1.SetError(_pageStartNugetServerTextBox, string.Empty);

            if (e.OldIndex > e.NewIndex)
            {
                if (_Mode == ActionType.Publish || _Mode == ActionType.Push || _Mode == ActionType.Remove || _Mode == ActionType.PackageStat)
                    e.NewIndex = 0;
                return;
            }

            if (e.NewIndex == 6)
            {
                _page7BuildPackageSummary.Text = string.Empty;
                _page7BuildPackageSummary.Controls.Clear();
            }

            if (this._wizard.SelectedPage == _pageStart)
            {
                this.contentNode.Nodes.Clear();
                this.libNode.Nodes.Clear();

                if (_pageStartModeCreateBasedOnProjectRadio.Checked)
                {
                    _Mode = ActionType.CreateFromProject;

                    if (this._pageStartCreateBasedOnProjectPathLabel.Text == _selectDefault)
                    {
                        errorProvider1.SetError(_pageStartCreateBasedOnProjectPathLabel, "Select a Project");
                        e.Cancel = true;
                        return;
                    }

                    _package.ProjectFileName = _pageStartCreateBasedOnProjectPathLabel.Text;
                    _package.ActiveConfigurationName = _pageStartCreateBasedOnProjectBuild.SelectedItem.ToString();

                    FileInfo projectFile = new FileInfo(_package.ProjectFileName);
                    _package.MetaData.Id = projectFile.Name.Replace(projectFile.Extension, string.Empty) + ".Package";
                    _page1IdTextBox.Text = _package.MetaData.Id;

                    PopulateContentTreeView(contentNode, new FileInfo(this._package.ProjectFileName).Directory);
                    PopulateLibTreeView(libNode, new DirectoryInfo(string.Format(@"{0}\bin\{1}\", new FileInfo(this._package.ProjectFileName).Directory.FullName, _package.ActiveConfigurationName)));
                }
                else if (_pageStartModeCreateBasedOnFolderRadio.Checked)
                {
                    _Mode = ActionType.CreateFromFolder;

                    if (this._pageStartCreateBasedOnFolderLabel.Text == _selectDefault)
                    {
                        errorProvider1.SetError(_pageStartCreateBasedOnFolderLabel, "Select a Folder");
                        e.Cancel = true;
                        return;
                    }

                    DirectoryInfo dir = new DirectoryInfo(this._pageStartCreateBasedOnFolderLabel.Text);
                    _package.MetaData.Id = dir.Name + ".Package";
                    _page1IdTextBox.Text = _package.MetaData.Id;
                    PopulateContentTreeView(contentNode, new DirectoryInfo(this._pageStartCreateBasedOnFolderLabel.Text));
                }
                else if (_pageStartModeCreateFromScratchRadio.Checked)
                    _Mode = ActionType.Create;
                else
                {
                    if (this._page6ApiKeyTextBox.Text == string.Empty && !this._pageStartModePackageStat.Checked)
                    {
                        errorProvider1.SetError(_pageStartApiKeyTextBox2, "Insert a valid Api Key");
                        e.Cancel = true;
                        return;
                    }

                    if (_pageStartModePushRadio.Checked)
                    {
                        if (this._pageStartExistingPackagePath.Text == _selectDefault)
                        {
                            errorProvider1.SetError(_pageStartExistingPackagePath, "Select a package");
                            e.Cancel = true;
                            return;
                        }

                        _Mode = ActionType.Push;
                        e.NewIndex = 8;
                    }
                    else
                    {
                        _pageStartPublishRemoveId.Text = _pageStartPublishRemoveId.Text.Trim();
                        if (!NugetPackageMetaData.IsValidId(_pageStartPublishRemoveId.Text))
                        {
                            errorProvider1.SetError(_pageStartPublishRemoveId, "Insert a valid package id");
                            e.Cancel = true;
                            return;
                        }

                        if (_pageStartPublishRemoveVersion.Text.Trim() == string.Empty && !this._pageStartModePackageStat.Checked)
                        {
                            errorProvider1.SetError(_pageStartPublishRemoveVersion, "Insert a package version");
                            e.Cancel = true;
                            return;
                        }

                        if (_pageStartModePublishRadio.Checked)
                        {
                            _Mode = ActionType.Publish;
                            e.NewIndex = 8;
                        }
                        else if (_pageStartModeRemoveFromLiveFeedRadio.Checked)
                        {
                            _Mode = ActionType.Remove;
                            e.NewIndex = 8;
                        }
                        else if (this._pageStartModePackageStat.Checked)
                        {
                            _page6BuildPanel.Text = string.Empty;
                            _Mode = ActionType.PackageStat;
                            e.NewIndex = 8;
                        }
                    }
                }
            }
            else if (this._wizard.SelectedPage == _page1)
            {
                if (this._page1AuthorslistBox.Items.Count == 0)
                    errorProvider1.SetError(this._page1AuthorslistBox, "Please provide Package Author(s)");

                this._package.MetaData.Authors = new List<string>();
                foreach (string s in _page1AuthorslistBox.Items)
                    this._package.MetaData.Authors.Add(s);

                if (errorProvider1.GetError(this._page1IdTextBox) != string.Empty ||
                    errorProvider1.GetError(this._page1IdTextBox) != string.Empty ||
                    errorProvider1.GetError(this._page1DescriptionDescriptionLabel) != string.Empty ||
                    errorProvider1.GetError(this._page1AuthorslistBox) != string.Empty)
                    e.Cancel = true;
            }
            else if (this._wizard.SelectedPage == _page2)
            {
                this._package.MetaData.Dependencies = new List<NugetDependencie>();
                foreach (NugetDependencie dep in this.dependenciesListBox.Items)
                    this._package.MetaData.Dependencies.Add(dep);
            }
            else if (this._wizard.SelectedPage == _page3)
            {
                CultureInfo culture = null;
                foreach (CultureInfo c in CultureInfo.GetCultures(CultureTypes.AllCultures))
                {
                    if (c.EnglishName == _page4LanguageComboBox.SelectedItem.ToString())
                    {
                        culture = c;
                        break;
                    }
                }
                this._package.MetaData.Language = culture;
            }
            else if (this._wizard.SelectedPage == _Page4)
            {
                this._package.MetaData.Owners = new List<string>();
                this._package.MetaData.Tags = new List<string>();
                foreach (string s in this._page4AddOwnersListBox.Items)
                    this._package.MetaData.Owners.Add(s);
                foreach (string s in this._page4TagsListBox.Items)
                    this._package.MetaData.Tags.Add(s);
            }
            else if (this._wizard.SelectedPage == _Page5)
            {
                SetPackageContent(this.contentNode);
                SetPackageLib(this.libNode);

                if (_package.Content.Count == 0 && _package.Lib.Count == 0)
                {
                    MessageBox.Show("Cannot create an empty Package", "", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    e.Cancel = true;
                }
            }
            else if (this._wizard.SelectedPage == _Page6)
            {
                this._package.OutputDirectories.Clear();
                foreach (string s in _page6OutputDirectories.Items)
                    this._package.OutputDirectories.Add(s);

                if (_package.OutputDirectories.Count == 0)
                {
                    errorProvider1.SetError(_page6OutputDirectoryLabel, "Please provide at least one output directory");
                    e.Cancel = true;
                    return;
                }

                if (_page6PushToServerCheckBox.Checked || _page6PublishToServerCheckBox.Checked)
                {
                    if (this._page6ApiKeyTextBox.Text == string.Empty)
                    {
                        errorProvider1.SetError(_page6ApiKeyTextBox, "Please provide a valid Api Key");
                        e.Cancel = true;
                        return;
                    }

                    if (this._pageStartNugetServerTextBox.Text == string.Empty)
                    {
                        errorProvider1.SetError(_pageStartNugetServerTextBox, "Please a source Server on the Wizard start page.");
                        e.Cancel = true;
                        return;
                    }
                }

                _package.PushPackage = this._page6PushToServerCheckBox.Checked;
                _package.PublishPackage = this._page6PublishToServerCheckBox.Checked;
                this._page7BuildPackageSummary.Text = _package.GetBuildSummary();
            }
        }

        private void _wizard_AfterSwitchPages(object sender, CristiPotlog.Controls.Wizard.AfterSwitchPagesEventArgs e)
        {
            if (_wizard.SelectedPage == _Page8)
            {
                _wizard.NextEnabled = false;
                if (_Mode != ActionType.PackageStat && _Mode != ActionType.Remove)
                    _wizard.BackEnabled = false;
                try
                {
                    _page6BuildPanel.Controls.Clear();
                    _lastBuildPanelEntryTop = 0;
                    string output = string.Empty;
                    bool success = false;
                    if (_Mode == ActionType.Create || _Mode == ActionType.CreateFromFolder || _Mode == ActionType.CreateFromProject)
                    {
                        string packageFilePath = string.Empty;
                        success = _package.Build(ref output, ref packageFilePath);
                        FileInfo file = new FileInfo(packageFilePath);
                        CreateBuildPanelEntry(success, output);
                        if (success)
                        {
                            string newFilePath = string.Empty;
                            foreach (string outputDirectory in _package.OutputDirectories)
                            {
                                newFilePath = string.Format(@"{0}\{1}", outputDirectory, file.Name);
                                try
                                {
                                    File.Copy(packageFilePath, newFilePath);
                                    CreateBuildPanelEntry(true, "Successfully copied to " + newFilePath);
                                }
                                catch (Exception ex)
                                {
                                    CreateBuildPanelEntry(true, "Error trying to copy to " + newFilePath);
                                }
                            }

                            if (_page6PushToServerCheckBox.Checked)
                            {
                                success = NugetPackage.Push(newFilePath, this._pageStartNugetServerTextBox.Text, this._page6ApiKeyTextBox.Text, ref output);
                                CreateBuildPanelEntry(success, output);

                                if (_page6PublishToServerCheckBox.Checked)
                                {
                                    success = NugetPackage.Publish(_package.MetaData.Id, _package.MetaData.Version, this._pageStartNugetServerTextBox.Text, this._page6ApiKeyTextBox.Text, ref output);
                                    CreateBuildPanelEntry(success, output);
                                }
                            }

                            //if (_page6SaveTemplatePath.Text != _selectDefault)
                            //{
                            //    // save template
                            //    SaveTemplate(_package, this._page6SaveTemplatePath.Text);
                            //}
                        }
                        file.Delete();
                    }
                    else
                    {
                        
                        switch (_Mode)
                        {
                            case ActionType.Push:
                                success = NugetPackage.Push(this._pageStartExistingPackagePath.Text, this._pageStartNugetServerTextBox.Text, this._page6ApiKeyTextBox.Text, ref output);
                                CreateBuildPanelEntry(success, output);
                                break;
                            case ActionType.Publish: 
                                success = NugetPackage.Publish(this._pageStartPublishRemoveId.Text, this._pageStartPublishRemoveVersion.Text, this._pageStartNugetServerTextBox.Text, this._page6ApiKeyTextBox.Text, ref output);
                                CreateBuildPanelEntry(success, output);
                                break;
                            case ActionType.Remove:
                                success = NugetPackage.Remove(this._pageStartPublishRemoveId.Text, this._pageStartPublishRemoveVersion.Text, this._pageStartNugetServerTextBox.Text, this._page6ApiKeyTextBox.Text, ref output);
                                CreateBuildPanelEntry(success, output);
                                break;
                            case ActionType.PackageStat:
                                NugetFeedService.GalleryFeedContext c = new NugetPublishWizard.NugetFeedService.GalleryFeedContext(new Uri(this._pageStartNugetServerTextBox.Text + "FeedService.svc"));
                                IQueryable<PublishedPackage> packages = (from p in c.Packages where p.Id == this._pageStartPublishRemoveId.Text select p);
                                if (_pageStartPublishRemoveVersion.Text != string.Empty)
                                    packages = (from p in packages where p.Version == _pageStartPublishRemoveVersion.Text select p);
                                if (packages.Count() != 0)
                                {
                                    List<PublishedPackage> packageList = packages.ToList();
                                    foreach (PublishedPackage package in packageList)
                                    {
                                        var dependson = (from p in c.Packages where p.Dependencies.Contains(package.Id.ToString()) select p);
                                        List<PublishedPackage> dependsonList = new List<PublishedPackage>();
                                        if (dependson.Count() != 0)
                                            dependsonList = dependson.ToList();
                                        CreateBuildPanelEntry(null, packageToString(package, dependsonList));

                                    }
                                } else 
                                {
                                    _wizard.SelectedPage = _pageStart; 
                                    MessageBox.Show(string.Format("Package not found on {0}", this._pageStartNugetServerTextBox.Text), "Not found", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                }
                                break;
                        }
                    }
                }
                finally
                {
                    _wizard.NextEnabled = true;
                }
            }
        }
        #endregion

        #region Package Content Treeview
        private void PopulateContentTreeView(TreeNode parent, DirectoryInfo directory)
        {
            foreach (DirectoryInfo dir in directory.GetDirectories())
            {
                TreeNode node = new TreeNode(dir.Name);
                if (dir.Attributes.HasFlag(FileAttributes.Hidden) || _ignoredDirectories.Contains(dir.Name.ToLower()))
                {
                    node.Checked = false;
                }
                else
                {
                    bool checkAndExpand = true;
                    if (!parent.IsExpanded)
                        checkAndExpand = false;
                    node.Checked = checkAndExpand;
                    node.Expand();
                }
                node.Tag = dir;
                parent.Nodes.Add(node);
                PopulateContentTreeView(node, dir);
            }

            foreach (FileInfo f in directory.GetFiles())
            {
                TreeNode n = new TreeNode(f.Name);
                n.Checked = !_ignoredFiles.Contains(f.Extension.ToLower());
                n.Tag = new NugetPackageFile()
                {
                    LocalFile = f
                };
                if (n.Checked)
                    n.Checked = parent.Checked;
                parent.Nodes.Add(n);
                (n.Tag as NugetPackageFile).PackageFile = n.FullPath;
            }
        }

        private void PopulateLibTreeView(TreeNode parent, DirectoryInfo directory)
        {
            foreach (FileInfo f in directory.GetFiles("*.dll"))
            {
                TreeNode n = new TreeNode(f.Name);
                n.Checked = true;
                n.Tag = new NugetPackageFile()
                {
                    LocalFile = f
                };
                parent.Nodes.Add(n);
                (n.Tag as NugetPackageFile).PackageFile = n.FullPath;
            }
        }

        private void packageContentTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            this.removeFileButton.Enabled = (this._page5PackageContentTreeView.SelectedNode.Level != 0);
            this.addFileButton.Enabled = (this._page5PackageContentTreeView.SelectedNode.Tag == null || this._page5PackageContentTreeView.SelectedNode.Tag.GetType() == typeof(DirectoryInfo));
            this.createDirectoryButton.Enabled = (this._page5PackageContentTreeView.SelectedNode.Tag == null || this._page5PackageContentTreeView.SelectedNode.Tag.GetType() == typeof(DirectoryInfo));
        }

        private void addFileButton_Click(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                TreeNode parent = this._page5PackageContentTreeView.SelectedNode;
                foreach (string fileName in openFileDialog.FileNames)
                {
                    FileInfo f = new FileInfo(fileName);
                    NugetPackageFile file = new NugetPackageFile()
                    {
                        LocalFile = f,
                        PackageFile = string.Format(@"{0}\{1}", parent.FullPath, f.Name)
                    };
                    TreeNode newNode = new TreeNode();
                    newNode.Tag = file;
                    newNode.Text = string.Format("{0} ({1})", f.Name, f.FullName);
                    newNode.Checked = true;
                    parent.Checked = true;
                    parent.Nodes.Add(newNode);
                }
            }
        }

        private void removeFileButton_Click(object sender, EventArgs e)
        {
            this._page5PackageContentTreeView.SelectedNode.Parent.Nodes.Remove(this._page5PackageContentTreeView.SelectedNode);
        }

        private void SetPackageContent(TreeNode parentNode)
        {
            foreach (TreeNode node in parentNode.Nodes)
            {
                if (node.Tag.GetType() == typeof(NugetPackageFile))
                {
                    if (node.Checked)
                        this._package.Content.Add((NugetPackageFile)node.Tag);
                }
            }

            foreach (TreeNode n in parentNode.Nodes)
                if (n.Checked)
                    SetPackageContent(n);
        }

        private void SetPackageLib(TreeNode parentNode)
        {
            foreach (TreeNode node in parentNode.Nodes)
            {
                if (node.Tag.GetType() == typeof(NugetPackageFile))
                {
                    if (node.Checked)
                        this._package.Lib.Add((NugetPackageFile)node.Tag);
                }
            }
        }
        #endregion

        #region Add / Remove Output Directory
        private void addOutputDirectorie_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                this._page6OutputDirectories.Items.Add(folderBrowserDialog.SelectedPath);
            }
        }

        private void outputDirectories_SelectedIndexChanged(object sender, EventArgs e)
        {
            this._page6RemoveOutputDirectorie.Enabled = true;
        }

        private void removeOutputDirectorie_Click(object sender, EventArgs e)
        {
            if (_page6OutputDirectories.SelectedItem != null)
                _page6OutputDirectories.Items.Remove(_page6OutputDirectories.SelectedItem);
        }
        #endregion

        #region Create Package Information Entry
        private string packageToString(PublishedPackage p, List<PublishedPackage> dependson)
        {
            StringBuilder b = new StringBuilder();
            b.AppendLine(string.Format("Package Id: {0}", p.Id));
            b.AppendLine(string.Format("Version: {0}", p.Version));
            b.AppendLine(string.Format("Title: {0}", p.Title));
            b.AppendLine(string.Format("Authors: {0}", p.Authors));
            if (p.Description != string.Empty)
            {
                b.AppendLine(string.Format("Description: {0}", p.Description));
                b.AppendLine();
            }
            b.AppendLine(string.Format("Published: {0}", p.Published));
            b.AppendLine(string.Format("LastUpdated: {0}", p.LastUpdated));
            b.AppendLine(string.Format("DownloadCount: {0}", p.DownloadCount));

            b.AppendLine(string.Format("LicenseUrl: {0}", p.LicenseUrl));
            b.AppendLine(string.Format("RequireLicenseAcceptance: {0}", p.RequireLicenseAcceptance));

            b.AppendLine(string.Format("ProjectUrl: {0}", p.ProjectUrl));
            b.AppendLine(string.Format("PackageSize: {0}", GetFileLengthString(p.PackageSize)));
            
            b.AppendLine(string.Format("Tags: {0}", p.Tags));
             
            if (dependson.Count == 0)
                b.AppendLine(string.Format("Packages Depend on \"{0}\": none", p.Id));
            else
            {
                b.AppendLine(string.Format("Packages Depend on \"{0}\":", p.Id));
                foreach (PublishedPackage d in dependson)
                {
                    b.AppendLine(string.Format("   + {0} ({1})", d.Id, d.Version));
                }
            }
            b.AppendLine("");
            b.AppendLine("");
            b.AppendLine("");

            return b.ToString();
        }
        #endregion

        private void createBasedOnFolderSelect_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                this._pageStartModeCreateBasedOnFolderRadio.Checked = true;
                this._pageStartCreateBasedOnFolderLabel.Text = folderBrowserDialog.SelectedPath;
            }

        }

        private void createBasedOnProjectSelect_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (openProjectFileDialog.ShowDialog() == DialogResult.OK)
            {
                this._pageStartModeCreateBasedOnProjectRadio.Checked = true;
                this._pageStartCreateBasedOnProjectPathLabel.Text = openProjectFileDialog.FileName;

                _pageStartCreateBasedOnProjectBuild.Items.Clear();

                // find builds
                string directoryPath = new FileInfo(openProjectFileDialog.FileName).DirectoryName;
                string binPath = string.Format(@"{0}\bin\", directoryPath);
                DirectoryInfo binDirectory = new DirectoryInfo(binPath);
                if (binDirectory.Exists)
                {
                    foreach (DirectoryInfo dir in binDirectory.GetDirectories())
                    {
                        if (!_ignoredDirectories.Contains(dir.Name))
                            _pageStartCreateBasedOnProjectBuild.Items.Add(dir.Name);
                    }
                    if (this._pageStartCreateBasedOnProjectBuild.Items.Count != 0)
                        this._pageStartCreateBasedOnProjectBuild.SelectedIndex = 0;
                    else
                        MessageBox.Show("The selected project´s bin directory doesnt contain a build", "", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
                else
                {
                    MessageBox.Show("The selected project doesnt contain an bin directory", "", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
        }

        private void navigateToNugetLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process nugetWebsite = new Process();
            nugetWebsite.StartInfo.FileName = @"http://nuget.org/";
            nugetWebsite.Start();
        }

        private void apiKeyTextBox2_TextChanged(object sender, EventArgs e)
        {
            if (sender != _page6ApiKeyTextBox)
                _page6ApiKeyTextBox.Text = _pageStartApiKeyTextBox2.Text;
        }

        private void apiKeyTextBox_TextChanged(object sender, EventArgs e)
        {
            Guid apiKey = Guid.Empty;
            if (Guid.TryParse(this._page6ApiKeyTextBox.Text, out apiKey))
            {
                _page6PushToServerCheckBox.Enabled = true;
                _page6PublishToServerCheckBox.Enabled = true;
                this._pageStartApiKeyTextBox2.Text = this._page6ApiKeyTextBox.Text;
                NugetPublishWizard.Properties.Settings.Default.ApiKey = this._page6ApiKeyTextBox.Text;
                NugetPublishWizard.Properties.Settings.Default.Save();
            }
            else
            {
                this._page6ApiKeyTextBox.Text = string.Empty;
                this._pageStartApiKeyTextBox2.Text = string.Empty;
                _page6PushToServerCheckBox.Enabled = false;
                _page6PublishToServerCheckBox.Enabled = false;
            }
        }

        private void selectExistingPackageSelect_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (openExistingFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this._pageStartExistingPackagePath.Text = openExistingFileDialog.FileName;
            }
        }

        private void CreateBuildPanelEntry(bool? success, string text)
        {
            Label l = new Label();
            if (success.HasValue)
                l.Text = "        " + text;
            else
                l.Text = text;

            l.TextAlign = ContentAlignment.TopLeft;
            l.ImageAlign = ContentAlignment.TopLeft;
            l.Padding = new System.Windows.Forms.Padding(24, 0, 3, 0);
            l.Dock = DockStyle.Top;
            l.AutoSize = true;

            if (success.HasValue)
            {
                if (success.Value)
                    l.Image = buildPanelIcon.Images[0];
                else
                    l.Image = buildPanelIcon.Images[1];
            }

            this._page6BuildPanel.Controls.Add(l);
        }

        public string GetFileLengthString(long length)
        {
            decimal[] fileStorageCapacityByBytes = { 1, 1024, 1048576, 1073741824, 1099511627776, 1125899906842620, 1152921504606850000 };
            string[] metricUnit = { "B", "KB", "MB", "GB", "TB", "PB" };

            for (int i = 0; i < fileStorageCapacityByBytes.Length; i++)
            {
                if (length < fileStorageCapacityByBytes[i + 1])
                {
                    decimal fileSize = length / fileStorageCapacityByBytes[i];
                    return System.Math.Round(fileSize, 2).ToString() + " " + metricUnit[i];
                }
            }

            return length.ToString();
        }

        private void _pageEndCodePlexLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Process p = new Process();
            p.StartInfo.FileName = "http://goo.gl/SlQfQ";
            p.Start();
        }

        private void createDirectoryButton_Click(object sender, EventArgs e)
        {
            CreateDirectoryForm form = new CreateDirectoryForm();
            if (form.ShowDialog() == DialogResult.OK && form.DirectoryName.Trim() != string.Empty)
            {
                TreeNode node = new TreeNode(form.DirectoryName);
                node.Checked = true;
                node.Expand();
                this._page5PackageContentTreeView.SelectedNode.Nodes.Add(node);
            }
        }

        private void _page6SaveTemplatePath_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            //if (saveTemplateDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            //    _page6SaveTemplatePath.Text = saveTemplateDialog.FileName;
        }

        public void LoadTemplate(string fileName)
        {
            if (!File.Exists(fileName))
                throw new FileNotFoundException("File not found", fileName);
            try
            {
                IFormatter formatter = new BinaryFormatter();
                Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                NugetPackage o = (NugetPackage) formatter.Deserialize(stream);
                stream.Close();
            }
            catch { }
        }

        public void SaveTemplate(NugetPackage package, string fileName)
        {
            if (File.Exists(fileName))
                File.Delete(fileName);

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream(fileName, FileMode.CreateNew);
            formatter.Serialize(stream, package);
            stream.Close();
        }

    }
}

